﻿using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;

namespace XTemplate.Utils.Extensions
{
    public static class StringExtension
    {
        public static bool _windows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

        /// <summary>
        /// 是否为空字符串或者null
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsEmpty(this string src)
        {
            return string.IsNullOrEmpty(src);
        }

        /// <summary>
        /// 是否为double类型
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsDouble(this string src)
        {
            return double.TryParse(src, out _);
        }

        /// <summary>
        /// 是否为int
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsInt(this string src)
        {
            return int.TryParse(src, out _);
        }

        /// <summary>
        /// 是否为long
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsLong(this string src)
        {
            return long.TryParse(src, out _);
        }

        /// <summary>
        /// 是否为decimal
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsDecimal(this string src)
        {
            return decimal.TryParse(src, out _);
        }

        /// <summary>
        /// 是否小于等于指定长度
        /// </summary>
        /// <param name="src"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static bool IsLengthLessEqual(this string src, int length)
        {
            if (src.IsEmpty()) return false;
            return src.Length <= length;
        }

        /// <summary>
        /// 是否是下划线或者字母开头
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsStartWithLetterUnderLine(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, "^[_a-zA-Z]+$");
        }

        /// <summary>
        /// 是否都是字母
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsAllLetter(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, "^[a-zA-Z]+$").Success;
        }

        /// <summary>
        /// 是否含有字母
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasLetter(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, "[a-zA-Z]+");
        }

        /// <summary>
        /// 是否是无符号数值
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsNumberic(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, "^([0]|([1-9]+\\d{0,}?), .[\\d]+)?$").Success;
        }

        /// <summary>
        /// 是否包含无符号数值
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasNumberic(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, "([0]|([1-9]+\\d{0,}?), .[\\d]+)?");
        }

        /// <summary>
        /// 是否是有符号数值
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsNumbericSign(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, "^-?\\d+$|^(-?\\d+)(\\.\\d+)?$").Success;
        }

        /// <summary>
        /// 是否包含有符号数值
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasNumbericSign(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, "-?\\d+$|^(-?\\d+)(\\.\\d+)?");
        }

        /// <summary>
        /// 是否都是数字或者字母
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsAllNumberLetter(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, "^[0-9a-zA-Z]+$").Success;
        }

        /// <summary>
        /// 是否含有数字或者字母
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasNumberLetter(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, "[0-9a-zA-Z]+");
        }

        /// <summary>
        /// 是否都是下划线数字和字母
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsAllNumberLetterUnderLine(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, "^[_0-9a-zA-Z]+$").Success;
        }

        /// <summary>
        /// 是否含有下划线数字和字母
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasNumberLetterUnderLine(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, "[_0-9a-zA-Z]+");
        }

        /// <summary>
        /// 是否是url
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsUrl(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, "^(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]$").Success;
        }

        /// <summary>
        /// 是否包含url
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasUrl(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, "(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]");
        }

        /// <summary>
        /// 是否是email
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsEmail(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, @"^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$").Success;
        }

        /// <summary>
        /// 是否包含email
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasEmail(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, @"[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+");
        }

        /// <summary>
        /// 是否是ip地址
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsIPAddress(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, @"^(([2][0-5][0-5]\.)|([1][0-9][0-9]\.)|([1-9]\d?\.)){3}(([2][0-5][0-5])|([1][0-9][0-9])|([1-9]\d?))$").Success;
        }

        /// <summary>
        /// 是否包含ip地址
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasIPAddress(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, @"(([2][0-5][0-5]\.)|([1][0-9][0-9]\.)|([1-9]\d?\.)){3}(([2][0-5][0-5])|([1][0-9][0-9])|([1-9]\d?))");
        }

        /// <summary>
        /// 是否是中国手机号
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsPhoneNumberCN(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, @"^1[3-8]\d{9}$").Success;
        }

        /// <summary>
        /// 是否包含中国手机号
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasPhoneNumberCN(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, @"1[3-9]\d{9}");
        }

        /// <summary>
        /// 是否是中国电话号
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsTelCN(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, @"^(0[0-9]{2,3}\-)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$", RegexOptions.IgnoreCase).Success;
        }

        /// <summary>
        /// 是否包含中国电话号
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasTelCN(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, @"(0[0-9]{2,3}\-)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?", RegexOptions.IgnoreCase);
        }

        /// <summary>
        /// 是否是有效中国身份证号
        /// </summary>
        /// <param name="str">输入字符</param>
        /// <returns>返回一个bool类型的值</returns>
        public static bool IsIDCardCN(this string src)
        {
            if (src.IsEmpty()) return false;
            switch (src.Length)
            {
                case 18:
                    {
                        return src.IsIDCardCN18();
                    }
                case 15:
                    {
                        return src.IsIDCardCN15();
                    }
                default:
                    return false;
            }
        }

        /// <summary>
        /// 验证输入字符串为中国18位的身份证号码
        /// </summary>
        /// <param name="src">输入字符</param>
        /// <returns>返回一个bool类型的值</returns>
        public static bool IsIDCardCN18(this string src)
        {
            if (src.IsEmpty()) return false;
            long n = 0;
            if (long.TryParse(src.Remove(17), out n) == false || n < Math.Pow(10, 16) || long.TryParse(src.Replace('x', '0').Replace('X', '0'), out n) == false)
            {
                return false;//数字验证
            }
            const string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
            if (address.IndexOf(src.Remove(2), StringComparison.Ordinal) == -1)
            {
                return false;//省份验证
            }
            string birth = src.Substring(6, 8).Insert(6, "-").Insert(4, "-");
            DateTime time;
            if (DateTime.TryParse(birth, out time) == false)
            {
                return false;//生日验证
            }
            string[] arrVarifyCode = ("1,0,x,9,8,7,6,5,4,3,2").Split(',');
            string[] wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(',');
            char[] ai = src.Remove(17).ToCharArray();
            int sum = 0;
            for (int i = 0; i < 17; i++)
            {
                sum += int.Parse(wi[i]) * int.Parse(ai[i].ToString());
            }
            int y = -1;
            Math.DivRem(sum, 11, out y);
            return arrVarifyCode[y] == src.Substring(17, 1).ToLower();
        }

        /// <summary>
        /// 验证输入字符串为中国15位的身份证号码
        /// </summary>
        /// <param name="src">输入字符</param>
        /// <returns>返回一个bool类型的值</returns>
        public static bool IsIDCardCN15(this string src)
        {
            if (src.IsEmpty()) return false;
            long n = 0;
            if (long.TryParse(src, out n) == false || n < Math.Pow(10, 14))
            {
                return false;//数字验证
            }
            const string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
            if (address.IndexOf(src.Remove(2), StringComparison.Ordinal) == -1)
            {
                return false;
            }
            string birth = src.Substring(6, 6).Insert(4, "-").Insert(2, "-");
            DateTime time;
            return DateTime.TryParse(birth, out time) != false;
        }

        /// <summary>
        /// 是否都是汉字
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsAllHanzi(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.Match(src, @"^[\u4e00-\u9fa5]+$").Success;
        }

        /// <summary>
        /// 是否包含汉字
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasAllHanzi(this string src)
        {
            if (src.IsEmpty()) return false;
            return Regex.IsMatch(src, @"[\u4e00-\u9fa5]+");
        }

        /// <summary>
        /// 是否包含非法字符
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool HasBadString(this string src)
        {
            if (src.IsEmpty()) return false;
            //列举一些特殊字符串
            const string badChars = "@,*,#,$,!,+,',=,--,%,^,&,?,(,), <,>,[,],{,},/,\\,;,:,\",\"\",delete,update,drop,alert,select";
            var arraryBadChar = badChars.Split(',');
            return arraryBadChar.Any(t => !src.Contains(t));
        }

        /// <summary>
        /// 是否是有效的datetime数值
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static bool IsDateTime(this string src)
        {
            if (src.IsEmpty()) return false;
            const string regexDate = @"[1-2]{1}[0-9]{3}((-|\/|\.){1}(([0]?[1-9]{1})|(1[0-2]{1}))((-|\/|\.){1}((([0]?[1-9]{1})|([1-2]{1}[0-9]{1})|(3[0-1]{1})))( (([0-1]{1}[0-9]{1})|2[0-3]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})(\.[0-9]{3})?)?)?)?$";
            if (Regex.IsMatch(src, regexDate))
            {
                //以下各月份日期验证，保证验证的完整性
                int indexY = -1;
                int indexM = -1;
                int indexD = -1;
                if (-1 != (indexY = src.IndexOf("-", StringComparison.Ordinal)))
                {
                    indexM = src.IndexOf("-", indexY + 1, StringComparison.Ordinal);
                    indexD = src.IndexOf(":", StringComparison.Ordinal);
                }
                else
                {
                    indexY = src.IndexOf("/", StringComparison.Ordinal);
                    indexM = src.IndexOf("/", indexY + 1, StringComparison.Ordinal);
                    indexD = src.IndexOf(":", StringComparison.Ordinal);
                }
                //不包含日期部分，直接返回true
                if (-1 == indexM)
                    return true;
                if (-1 == indexD)
                {
                    indexD = src.Length + 3;
                }
                int iYear = Convert.ToInt32(src.Substring(0, indexY));
                int iMonth = Convert.ToInt32(src.Substring(indexY + 1, indexM - indexY - 1));
                int iDate = Convert.ToInt32(src.Substring(indexM + 1, indexD - indexM - 4));
                //判断月份日期
                if ((iMonth < 8 && 1 == iMonth % 2) || (iMonth > 8 && 0 == iMonth % 2))
                {
                    if (iDate < 32)
                        return true;
                }
                else
                {
                    if (iMonth != 2)
                    {
                        if (iDate < 31)
                            return true;
                    }
                    else
                    {
                        //闰年
                        if ((0 == iYear % 400) || (0 == iYear % 4 && 0 < iYear % 100))
                        {
                            if (iDate < 30)
                                return true;
                        }
                        else
                        {
                            if (iDate < 29)
                                return true;
                        }
                    }
                }
            }
            return false;
        }

        public static string ReplacePath(this string path)
        {
            if (string.IsNullOrEmpty(path))
                return "";
            if (_windows)
                return path.Replace("/", "\\");
            return path.Replace("\\", "/");
        }

        /// <summary>
        /// 判断是不是正确的手机号码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsPhoneNo(this string input)
        {
            if (string.IsNullOrEmpty(input))
                return false;
            if (input.Length != 11)
                return false;

            if (new Regex(@"^1[3578][01379]\d{8}$").IsMatch(input)
                || new Regex(@"^1[34578][01256]\d{8}").IsMatch(input)
                || new Regex(@"^(1[012345678]\d{8}|1[345678][0123456789]\d{8})$").IsMatch(input)
                )
                return true;
            return false;
        }

        public static bool GetGuid(this string guid, out Guid outId)
        {
            Guid emptyId = Guid.Empty;
            return Guid.TryParse(guid, out outId);
        }

        public static bool IsGuid(this string guid)
        {
            Guid newId;
            return guid.GetGuid(out newId);
        }

        public static bool IsInt(this object obj)
        {
            if (obj == null)
                return false;
            bool reslut = Int32.TryParse(obj.ToString(), out int _number);
            return reslut;
        }

        public static bool IsDate(this object str)
        {
            return str.IsDate(out _);
        }

        public static bool IsDate(this object str, out DateTime dateTime)
        {
            dateTime = DateTime.Now;
            if (str == null || str.ToString() == "")
            {
                return false;
            }
            return DateTime.TryParse(str.ToString(), out dateTime);
        }

        /// <summary>
        /// 根据传入格式判断是否为小数
        /// </summary>
        /// <param name="str"></param>
        /// <param name="formatString">18,5</param>
        /// <returns></returns>
        public static bool IsNumber(this string str, string formatString)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            int precision = 32;
            int scale = 5;
            try
            {
                if (string.IsNullOrEmpty(formatString))
                {
                    precision = 10;
                    scale = 2;
                }
                else
                {
                    string[] numbers = formatString.Split(',');
                    precision = Convert.ToInt32(numbers[0]);
                    scale = numbers.Length == 0 ? 2 : Convert.ToInt32(numbers[1]);
                }
            }
            catch { };
            return IsNumber(str, precision, scale);
        }

        /**/

        /// <summary>
        /// 判断一个字符串是否为合法数字(指定整数位数和小数位数)
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="precision">整数位数</param>
        /// <param name="scale">小数位数</param>
        /// <returns></returns>
        public static bool IsNumber(this string str, int precision, int scale)
        {
            if ((precision == 0) && (scale == 0))
            {
                return false;
            }
            string pattern = @"(^\d{1," + precision + "}";
            if (scale > 0)
            {
                pattern += @"\.\d{0," + scale + "}$)|" + pattern;
            }
            pattern += "$)";
            return Regex.IsMatch(str, pattern);
        }

        public static bool IsNullOrEmpty(this object str)
        {
            if (str == null)
                return true;
            return str.ToString() == "";
        }

        public static int GetInt(this object obj)
        {
            if (obj == null)
                return 0;
            int.TryParse(obj.ToString(), out int _number);
            return _number;
        }

        /// <summary>
        /// 获取 object 中的枚举值
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static long GetLong(this object obj)
        {
            if (obj == null)
                return 0;

            try
            {
                return Convert.ToInt64(Convert.ToDouble(obj));
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取 object 中的 float
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>

        public static float GetFloat(this object obj)
        {
            if (System.DBNull.Value.Equals(obj) || null == obj)
                return 0;

            try
            {
                return float.Parse(obj.ToString());
            }
            catch
            {
                return 0;
            }
        }

        public static double GetDouble(this object obj)
        {
            if (System.DBNull.Value.Equals(obj) || null == obj)
                return 0;

            try
            {
                return Convert.ToDouble(obj);
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取 object 中的 decimal
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static decimal GetDecimal(this object obj)
        {
            if (System.DBNull.Value.Equals(obj) || null == obj)
                return 0;

            try
            {
                return Convert.ToDecimal(obj);
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取 object 中的 decimal
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static dynamic GetDynamic(this object obj)
        {
            if (System.DBNull.Value.Equals(obj) || null == obj)
                return null;

            try
            {
                string str = obj.ToString();
                if (str.IsNumber(25, 15)) return Convert.ToDecimal(obj);
                else return str;
            }
            catch
            {
                return string.Empty;
            }
        }

        public static DateTime? GetDateTime(this object obj)
        {
            if (System.DBNull.Value.Equals(obj) || null == obj)
                return null;
            bool result = DateTime.TryParse(obj.ToString(), out DateTime dateTime);
            if (!result)
                return null;
            return dateTime;
        }

        public static object ParseTo(this string str, string type)
        {
            switch (type)
            {
                case "System.Boolean":
                    return ToBoolean(str);

                case "System.SByte":
                    return ToSByte(str);

                case "System.Byte":
                    return ToByte(str);

                case "System.UInt16":
                    return ToUInt16(str);

                case "System.Int16":
                    return ToInt16(str);

                case "System.uInt32":
                    return ToUInt32(str);

                case "System.Int32":
                    return str.ToInt32();

                case "System.UInt64":
                    return ToUInt64(str);

                case "System.Int64":
                    return ToInt64(str);

                case "System.Single":
                    return ToSingle(str);

                case "System.Double":
                    return ToDouble(str);

                case "System.Decimal":
                    return ToDecimal(str);

                case "System.DateTime":
                    return ToDateTime(str);

                case "System.Guid":
                    return ToGuid(str);
            }
            throw new NotSupportedException(string.Format("The string of \"{0}\" can not be parsed to {1}", str, type));
        }

        public static sbyte? ToSByte(this string value)
        {
            sbyte value2;
            if (sbyte.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static byte? ToByte(this string value)
        {
            byte value2;
            if (byte.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static ushort? ToUInt16(this string value)
        {
            ushort value2;
            if (ushort.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static short? ToInt16(this string value)
        {
            if (short.TryParse(value, out short value2))
            {
                return value2;
            }
            return null;
        }

        public static uint? ToUInt32(this string value)
        {
            uint value2;
            if (uint.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static ulong? ToUInt64(this string value)
        {
            ulong value2;
            if (ulong.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static long? ToInt64(this string value)
        {
            long value2;
            if (long.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static float? ToSingle(this string value)
        {
            float value2;
            if (float.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static double? ToDouble(this string value)
        {
            double value2;
            if (double.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static decimal? ToDecimal(this string value)
        {
            decimal value2;
            if (decimal.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static bool? ToBoolean(this string value)
        {
            bool value2;
            if (bool.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static Guid? ToGuid(this string str)
        {
            Guid value;
            if (Guid.TryParse(str, out value))
            {
                return value;
            }
            return null;
        }

        public static DateTime? ToDateTime(this string value)
        {
            DateTime value2;
            if (DateTime.TryParse(value, out value2))
            {
                return value2;
            }
            return null;
        }

        public static int? ToInt32(this string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return null;
            }
            int value;
            if (int.TryParse(input, out value))
            {
                return value;
            }
            return null;
        }

        /// <summary>
        /// 替换空格字符
        /// </summary>
        /// <param name="input"></param>
        /// <param name="replacement">替换为该字符</param>
        /// <returns>替换后的字符串</returns>
        public static string ReplaceWhitespace(this string input, string replacement = "")
        {
            return string.IsNullOrEmpty(input) ? null : Regex.Replace(input, "\\s", replacement, RegexOptions.Compiled);
        }

        /// <summary>
        /// 超过指定长度使用指定省略符代替
        /// </summary>
        /// <param name="value"></param>
        /// <param name="length"></param>
        /// <param name="ellipsis"></param>
        /// <returns></returns>
        public static string Ellipsis(this string value, int length, string ellipsis = "...")
        {
            if (!value.IsLengthLessEqual(length))
            {
                value = value.Substring(0, length);
                value += ellipsis;
            }
            return value;
        }

        /// <summary>
        /// 将驼峰字符串转为下划线字符串
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string UnderscoreName(this string name)
        {
            StringBuilder result = new StringBuilder();
            if (name != null && name.Length > 0)
            {
                // 将第一个字符处理成大写
                result.Append(name.Substring(0, 1).ToUpper());
                // 循环处理其余字符
                for (int i = 1; i < name.Length; i++)
                {
                    string s = name.Substring(i, i + 1);
                    // 在大写字母前添加下划线
                    if (s.Equals(s.ToUpper()) && !char.IsDigit(s[0]))
                    {
                        result.Append("_");
                    }
                    // 其他字符直接转成大写
                    result.Append(s.ToUpper());
                }
            }
            return result.ToString();
        }

        /// <summary>
        /// 将下划线字符串转为驼峰字符串
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string CamelName(this string name)
        {
            StringBuilder result = new StringBuilder();
            // 快速检查
            if (name == null || name.IsEmpty())
            {
                // 没必要转换
                return "";
            }
            else if (!name.Contains("_"))
            {
                // 不含下划线，仅将首字母小写
                return name.Substring(0, 1).ToLower() + name.Substring(1);
            }
            // 用下划线将原始字符串分割
            string[] camels = name.Split('_');
            foreach (string camel in camels)
            {
                // 跳过原始字符串中开头、结尾的下换线或双重下划线
                if (camel.IsEmpty())
                {
                    continue;
                }
                // 处理真正的驼峰片段
                if (result.Length == 0)
                {
                    // 第一个驼峰片段，全部字母都小写
                    result.Append(camel.ToLower());
                }
                else
                {
                    // 其他的驼峰片段，首字母大写
                    result.Append(camel.Substring(0, 1).ToUpper());
                    result.Append(camel.Substring(1).ToLower());
                }
            }
            return result.ToString();
        }

        /// <summary>
        /// 将下划线字符串转为驼峰字符串首字母大写
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string UpCamelName(this string name)
        {
            var cameName = name.CamelName();
            return cameName.Substring(0, 1).ToUpper() + cameName.Substring(1);
        }

        private static char[] randomConstant ={
        '0','1','2','3','4','5','6','7','8','9',
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
        'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
        };

        /// <summary>
        /// 生成指定长度的随机数
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string GenerateRandomNumber(this int length)
        {
            System.Text.StringBuilder newRandom = new System.Text.StringBuilder(62);
            Random rd = new Random();
            for (int i = 0; i < length; i++)
            {
                newRandom.Append(randomConstant[rd.Next(62)]);
            }
            return newRandom.ToString();
        }
    }
}